package utils.version3;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class ConnectionUtil {
    private static final String driverClassName = "com.mysql.jdbc.Driver";
    private static final String url = "jdbc:mysql://localhost:3306/demo";
    private static final String username = "root";
    private static final String password = "root";

    static {
        try {
            Class.forName(driverClassName);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //   ****************************开始1111×××××××××××××××××××××××
    //连接对象创建出来了，但存放到哪里去呢？（不保存起来，无法保证多个dao使用的是同一个connection对象）
    // 用一个全局的静态Connection变量来存（因为此方法是静态的）？然后添加一个方法返回此全局变量？
    //这样的话，作为ConnectionUtil类的使用者，到底使用getConnection还是getNewConnection方法来创建Connection呢？
    //还有一个更严重的问题是：这个局部变量是静态的，导致多线程情况下，此变量会是一个共享变量。也就会产生线程不安全的问题。
  /*  private  static Connection newConnection;
    public static Connection getConnection(){
        Connection connection = null;

        try {
            connection =  DriverManager.getConnection(url, username, password);

            newConnection = connection;

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  connection;
    }

    public static  Connection getNewConnection(){
        return  newConnection;
    }*/
    //   ****************************结束111111×××××××××××××××××××××××


    //*******************************开始222222×××××××××××××××××××××××××××××
    //先解决第一个问题，不知道该使用getConnection还是getNewConnection的问题,让用户同意使用getCurrentConnection方法
    //也就是说这个方法有2个基本功能，一是直接返回一个曾经创建出来的对象，另一个是创建并保存Connection对象。
    //基本逻辑一定是这样的：从一个保存连接的类型中（比如Map，List之类），传递一个信息给这个容器，并返回一个Connection对象。
    //这里决定采用线程id
   /* private static Map<Long, Connection> connectionMap = new HashMap<>();
    public  static Connection getCurrentConnection(){
          Connection connection = connectionMap.get(Thread.currentThread().getId());
        try {
            if (connection == null || connection.isClosed()) {

                connection = DriverManager.getConnection(url, username, password);
                connectionMap.put(Thread.currentThread().getId(), connection);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return connection;
    }*/

    /**
     * 上面的方法解决了同一个方法返回连接的问题，在单线程下也没有任何问题，但是在多线程环境下就会产生问题
     * 因为HashMap并不是一个线程安全的类型，所以我们需要选择一个线程安全的类型来处理,比如Hashtable
     */
   /* private static Map<Long, Connection> connectionMap = new Hashtable<>();

    public static Connection getCurrentConnection() {
        Connection connection = connectionMap.get(Thread.currentThread().getId());
        try {
            if (connection == null || connection.isClosed()) {
                connection = DriverManager.getConnection(url, username, password);
                connectionMap.put(Thread.currentThread().getId(), connection);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
*/
    /**
     * 或者下面的线程安全的实现
     */

    private static ThreadLocal<Connection> connectionMap = new ThreadLocal<>();

    public static Connection getCurrentConnection() {
        Connection connection = connectionMap.get();
        try {
            if (connection == null || connection.isClosed()) {
                connection = DriverManager.getConnection(url, username, password);
                connectionMap.set(connection);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
    public static void start() {
        Connection connection = getCurrentConnection();
        try {
            connection.setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void commit() {
        try {
            getCurrentConnection().commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void rollback() {
        try {
            getCurrentConnection().rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close() {
        try {
            getCurrentConnection().close();
            connectionMap.remove(); //针对ThreadLocal实现
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    //   ****************************结束22222×××××××××××××××××××××××
    /*public static Connection getConnection(){
        Connection connection = null;

        try {
            connection =  DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return  connection;
    }*/


}
